\begin{lstlisting}
def relative_differential_probabilities(D1,D2,PT):
    """
    Given 2-character strings D1 and D2 representing XY-ZW and XY-QR, 
    return the dictionary of probabilities (P(XY)P(ZW)P(QR)), scaled 
    to a probability function on the set {A,..,Z}^2.
    PT is a sample plaintext for use in determining the 2-character 
    frequency distribution of English.
    """
    if len(D1) != 2 or len(D2) != 2:                                             
        raise ValueError, \
           "Arguments D1 (= %s) and D2 (= %s) must have length 2" % (D1, D2)
    AZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    r1 = AZ.index(D1[0]); s1 = AZ.index(D1[1])
    r2 = AZ.index(D2[0]); s2 = AZ.index(D2[1])
    FD = RealField()(0)                                                     
    D2 = {}
    F2 = frequency_distribution(PT,2)                                  
    for i1 in range(26):
       X1 = AZ[i1]; X2 = AZ[(i1-r1)%26]; X3 = AZ[(i1-r2)%26]
       for j1 in range(26):
            Y1 = AZ[j1]; Y2 = AZ[(j1-s1)%26]; Y3 = AZ[(j1-s2)%26]
            D2[X1+Y1] = F2[X1+Y1] * F2D[X2+Y2] * F2D[X3+Y3]
            FD += D2[X1+Y1]
    c = 1/FD
    for i1 in range(26):
        X1 = AZ[i1]
        for j1 in range(26):
            Y1 = AZ[j1]
            D2[X1+Y1] *= c
    return D2
\end{lstlisting}
